package pyrachnid.model.robot_model;

import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;

import pyrachnid.model.ground_model.Cell;
import pyrachnid.model.ground_model.Map;
import pyrachnid.model.scenar_model.Scenario;


public class Manager {
	private static Manager instance;
	private Map _map;
	private Scenario _scenario;
	private ArrayList<Robot> _robots;
	private Timer _timer;
	
	
	 public static Manager getInstance() {
	    if (null == instance) { // Premier appel
	        instance = new Manager();
	    }
	    return instance;
	}
	 
	private Manager() {}
	
	public void loadSenario(Scenario p_scenario)
	{
		_scenario = p_scenario;
		_map = p_scenario.getMap();
		_robots = p_scenario.getRobotList();
	}
	
	// Update all the element of the simulation
	public void update() {
		// Time since the last top
		int time = _scenario.getSpeed();
		
		// For all fires
		ArrayList<Cell> cellFire = _scenario.getMap().getFires();
		for(int i = 0; i < cellFire.size(); i++)
		{
			// update the intencity of all fire, and compute new fire
			cellFire.get(i).update(time, _scenario);
			
			// If a fire is not allocated to a robot
			if(!cellFire.get(i).getIsAllocated()) {
				Cell cellInFire = cellFire.get(i);
				Robot robot = findRobotToFire(cellInFire);

				// Set the robot allocated. No new search for this robot
				if(robot != null)
				{
					cellFire.get(i).setIsAllocated(true);
					robot.setAllocateFire(cellInFire);
				}
			}
		}

		// For all robot
		for(Robot robot : _robots)
		{
			if(robot != null)
			{
				robot.update(time);
			}
		}
		
		_scenario.getWind().update(time);
	}

	// Search the robot not allocated the most speed to acces to the cell
	private Robot findRobotToFire(Cell p_cell)
	{
		Robot robot = null;
		Double temps = -1.0; // Pour le premier passage de la condition
		
		for(int i = 0; i < _robots.size(); i++)
		{
			Robot robotCurent = _robots.get(i);
			if(!robotCurent.getIsAllocated())
			{	
				Cell sourceCell = _map.getGround()[robotCurent.getPositionX()][robotCurent.getPositionY()];
				double tempsCurent = robotCurent.getTimeToCell(_map, sourceCell, p_cell);
				
				if((tempsCurent < temps || temps == -1.0) && tempsCurent != -1.0)
				{
					temps = tempsCurent;
					robot = robotCurent;
				}
			}
		}

		return robot;
	}
	
	// Run the timer
	public void start() {
		_timer = new Timer();
		_timer.schedule (new MyTimer(this), 0, _scenario.getSpeed());
	}
	
	// Stop the timer
	public void stop() {
		_timer.cancel();
	}

	public Map getMap() {
		return _map;
	}

	public void setMap(Map map) {
		_map = map;
	}

	public Scenario getScenario() {
		return _scenario;
	}

	public void setScenario(Scenario scenario) {
		this._scenario = scenario;
	}

	public ArrayList<Robot> getRobot() {
		return _robots;
	}

	public void setRobot(ArrayList<Robot> p_robots) {
		_robots = p_robots;
	}
	
	// Timer use to launch a update at the manager 
	public class MyTimer extends TimerTask {
		Manager _manager;
		
		public MyTimer(Manager p_manager) {
			super();
			_manager = p_manager;
		}
		
		@Override
		public void run() {
			try {
	            _manager.update();
			} catch (Exception e) {
	            e.printStackTrace();
			}
		}
	}
}